package com.study.gupao.proxy.gpproxy;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.File;
import java.io.FileWriter;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

/**
 * @ClassName: GPProxy
 * @Description: 模仿jdk动态代理
 * @author: Adminstrator
 * @Date: 2019-03-12 22:13
 */
public class GPProxy {

    public static final String ln = "\r\n";

    public static Object newProxyInstance(GPClassLoader loader,Class<?>[] interfaces,
                  GPInvocationHandler h) throws IllegalArgumentException{
        try{
            //1、动态生成源代码
            String src = generateSrc(interfaces);

            //2、java文件输出到磁盘
            String filePath = GPProxy.class.getResource("").getPath();
            File file = new File(filePath + "$Proxy0.class");
            FileWriter writer = new FileWriter(file);
            writer.write(src);
            writer.flush();
            writer.close();

            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(null, null, null);
            Iterable<? extends JavaFileObject> javaFileObjects = standardFileManager.getJavaFileObjects(file);
            JavaCompiler.CompilationTask task = compiler.getTask(null, standardFileManager, null, null, null, javaFileObjects);
            task.call();
            System.out.println(src);
        }catch (Exception e){

        }
        return null;
    }

    private static String generateSrc(Class<?>[] interfaces) {
        StringBuffer buffer = new StringBuffer();
        buffer.append("package com.study.gupao.proxy.gpproxy;"+ ln);
        buffer.append("import com.study.gupao.proxy.Person;"+ln);
        buffer.append("import java.lang.reflect.*;"+ln);
        buffer.append("public class $Proxy0 implements "+ interfaces[0].getName()+"{"+ln);
        buffer.append("GPInvocationHandler h;"+ ln);
        buffer.append("public $Proxy0(GPInvocationHandler h) {"+ ln);
        buffer.append("this.h = h;"+ ln);
        buffer.append("}"+ ln);

        for(Method m : interfaces[0].getMethods()){
            buffer.append("public "+ m.getReturnType().getName()+" "+ m.getName()+"(){"+ln);
            buffer.append("try{");
            buffer.append("Method method = "+ interfaces[0].getName()+".class.getMethod(\""+m.getName()+"\",new Class[]{});"+ln);
            buffer.append("this.h.invoke(this,method,null);"+ln);
            buffer.append("}catch(Throwable e){"+ln);
            buffer.append("e.printStackTrace();");
            buffer.append("}"+ ln);
            buffer.append("}");

        }
        buffer.append("}");

        return buffer.toString();
    }
}
